import {
  getEditorProvider,
  IEditorContainerController,
  IEditorController,
  IEditorProvider,
  PanelItemController,
  PanelItemEventName,
} from '@ibiz-template/runtime'
import { IPanelField } from '@ibiz/model-core'
import { PanelFieldState } from './i-biz-panel-field.state'

/**
 * 面板按钮控制器
 *
 * @export
 * @class PanelFieldController
 * @extends {PanelItemController<IPanelField>}
 */
export class PanelFieldController
  extends PanelItemController<IPanelField>
  implements IEditorContainerController
{
  declare state: PanelFieldState

  unitName: string | undefined = undefined

  /**
   * 值格式化
   * @author lxm
   * @date 2023-05-24 05:46:56
   * @readonly
   * @type {(string | undefined)}
   */
  get valueFormat(): string | undefined {
    return this.model.valueFormat
  }

  get dataType(): number | undefined {
    return undefined
  }

  get context(): IContext {
    return this.panel.context
  }

  get params(): IParams {
    return this.panel.params
  }

  /**
   * 父容器数据对象数据
   * @author lxm
   * @date 2023-07-15 01:33:58
   * @readonly
   * @type {IData}
   */
  get data(): IData {
    return this.dataParent.data
  }

  /**
   * 面板属性成员的值
   * @author lxm
   * @date 2023-07-14 02:30:58
   * @readonly
   */
  get value(): string | number {
    return this.data[this.model.id!]
  }

  /**
   * 编辑器控制器
   *
   * @author lxm
   * @date 2022-08-24 20:08:42
   * @type {IEditorController}
   */
  editor?: IEditorController

  /**
   * 编辑器适配器
   *
   * @author lxm
   * @date 2022-08-24 20:08:42
   */
  editorProvider?: IEditorProvider

  protected createState(): PanelFieldState {
    return new PanelFieldState(this.parent?.state)
  }

  /**
   * 值校验
   * @return {*}  {Promise<boolean>}
   * @memberof PanelFieldController
   */
  async validate(): Promise<boolean> {
    // 目前仅支持空值校验
    if (this.state.visible && !this.model.allowEmpty && !this.value) {
      this.state.error =
        this.editor?.model.placeHolder ||
        ibiz.i18n.t('vue3Util.panelComponent.cannotEmpty', {
          caption: this.model.caption,
        })
      return false
    }
    this.state.error = null
    return true
  }

  /**
   * 初始化
   *
   * @author lxm
   * @date 2022-08-24 20:08:42
   * @protected
   * @returns {*}  {Promise<void>}
   */
  protected async onInit(): Promise<void> {
    await super.onInit()
    // 空输入默认值
    this.state.required = !this.model.allowEmpty
    if (
      this.context.srfreadonly !== true &&
      this.context.srfreadonly !== 'true' &&
      this.model.editor?.readOnly
    ) {
      this.state.readonly = this.model.editor?.readOnly || false
    }
    // 初始化编辑器控制器,除了隐藏都会需要适配器
    if (this.model.editor && this.model.editor.editorType !== 'HIDDEN') {
      this.editorProvider = await getEditorProvider(this.model.editor)
      if (this.editorProvider) {
        this.editor = await this.editorProvider.createController(this.model.editor, this)
      }
    }
  }

  /**
   * 设置面板数据的值
   *
   * @author lxm
   * @date 2022-08-24 10:08:40
   * @param {unknown} value 要设置的值
   * @param {string} name 要设置的面板数据的属性名称
   */
  async setDataValue(value: unknown, name?: string): Promise<void> {
    const { id } = this.model
    name = name || id
    if (this.dataParent.setDataValue) {
      await this.dataParent.setDataValue(name!, value)
    }
    await this.validate()
    this.panel.evt.emit('onPanelItemEvent', {
      panelItemName: this.model.id!,
      panelItemEventName: PanelItemEventName.CHANGE,
    })
  }

  /**
   * 聚焦事件
   * @author lxm
   * @date 2023-10-11 05:03:26
   */
  onFocus(event: MouseEvent): void {
    this.panel.evt.emit('onPanelItemEvent', {
      panelItemName: this.model.id!,
      panelItemEventName: PanelItemEventName.FOCUS,
      event,
    })
  }

  /**
   * 失焦事件
   * @author lxm
   * @date 2023-10-11 05:03:26
   */
  onBlur(event: MouseEvent): void {
    this.panel.evt.emit('onPanelItemEvent', {
      panelItemName: this.model.id!,
      panelItemEventName: PanelItemEventName.BLUR,
      event,
    })
  }

  /**
   * 回车事件
   * @author lxm
   * @date 2023-10-11 05:03:26
   */
  onEnter(event: MouseEvent): void {
    this.panel.evt.emit('onPanelItemEvent', {
      panelItemName: this.model.id!,
      panelItemEventName: PanelItemEventName.ENTER,
      event,
    })
  }
}
